<template>
  <div class="left-panel">
    <div class="image-section">
      <img
        :src="`/img/${currentDeviceImageName}`"
        alt="Device Diagram"
        class="device-image"
        @load="onImageLoad"
        ref="deviceImageRef"
      />
      <div
        v-for="point in sensorPoints"
        :key="point.id"
        :id="`dot${point.id}`"
        class="sensor-box"
        :style="{
          top: point.top,
          left: point.left,
          borderColor: CATEGORY_COLOR_MAP[point.colorCategory] || CATEGORY_COLOR_MAP['默认'],
          color: CATEGORY_COLOR_MAP[point.colorCategory] || CATEGORY_COLOR_MAP['默认'],
        }"
        @click="$emit('sensor-clicked', point.id)"
      >
        <!-- <span class="sensor-id">{{ point.id }}</span> -->
        <span class="sensor-value">{{ point.latestValue }} {{ point.unit }}</span>
      </div>
    </div>

    <div class="device-controls-inline">
      <button
        v-for="device in devices"
        :key="device.id"
        :class="{
          active: activeDeviceName === device.name,
          'has-undisposed-alarms': device.undisposedAlarmCount > 0,
        }"
        @click="emitSwitchDevice(device.name)"
        :title="
          device.undisposedAlarmCount > 0 ? `未处理报警: ${device.undisposedAlarmCount}个` : ''
        "
      >
        {{ device.name }}
        <span v-if="device.undisposedAlarmCount > 0" class="alarm-badge">
          {{ device.undisposedAlarmCount }}
        </span>
      </button>
      <!-- <button @click="clearAndStartMonitor" class="control-button">清空数据并开始模拟</button> -->
    </div>
  </div>
</template>

<script setup>
import { ref, computed, watch, onMounted, nextTick, onUnmounted, defineEmits } from 'vue'

const props = defineProps({
  currentDevice: String,
  currentDeviceImageName: String, // <-- 关键：新增 Prop 来接收图片文件名
  sensorPoints: Array,
  devices: Array,
  activeDeviceName: String,
})

const emit = defineEmits(['sensor-clicked', 'switch-device'])

const deviceImageRef = ref(null)
// currentDeviceImage computed property is now simplified as it directly uses the prop
const imageLoaded = ref(false)
const currentDeviceImage = computed(() => `/img/${props.currentDeviceImageName}`)

const CATEGORY_COLOR_MAP = {
  主要: 'red',
  相关: 'orange',
  其他: 'gray',
  默认: 'gray',
}

// -------------------------------------------------------------
// 传感器点位定位核心逻辑
// -------------------------------------------------------------

const positionSensorBoxes = () => {
  const deviceImage = deviceImageRef.value
  if (!deviceImage || !imageLoaded.value) {
    console.warn(
      'LeftPanel: Cannot position sensor boxes. Image not loaded yet or element not found.',
    )
    return
  }

  const imageRect = deviceImage.getBoundingClientRect()
  const imgActualWidth = imageRect.width
  const imgActualHeight = imageRect.height
  const imgActualLeftInPanel = deviceImage.offsetLeft
  const imgActualTopInPanel = deviceImage.offsetTop // 正确获取图片在其父容器中的顶部偏移量

  props.sensorPoints.forEach((point) => {
    const dotElement = document.getElementById(`dot${point.id}`)
    if (!dotElement) {
      console.warn(`LeftPanel: Sensor box element dot${point.id} not found for positioning.`)
      return
    }

    const percentageLeft = parseFloat(point.left) / 100
    const percentageTop = parseFloat(point.top) / 100

    // 计算传感器点位在图片上的像素坐标
    // 这里的计算是：图片在其父容器内的左/上偏移 + (图片实际宽度/高度 * 百分比位置)
    const dotPixelLeftOnImage = imgActualLeftInPanel + percentageLeft * imgActualWidth
    const dotPixelTopOnImage = imgActualTopInPanel + percentageTop * imgActualHeight // 修正：使用 imgActualTopInPanel

    dotElement.style.left = `${dotPixelLeftOnImage}px`
    dotElement.style.top = `${dotPixelTopOnImage}px`
  })
  console.log('LeftPanel: Sensor boxes positioned based on actual image dimensions.')
}

// -------------------------------------------------------------
// 事件处理和生命周期
// -------------------------------------------------------------

// 图片加载完成事件处理器

const onImageLoad = () => {
  imageLoaded.value = true
  console.log('LeftPanel: Device image onload event fired. Image state set to loaded.')
  nextTick(() => {
    positionSensorBoxes()
  })
}

// 监听 currentDevice 或 sensorPoints 的变化
watch(
  () => [props.currentDevice, props.sensorPoints, props.currentDeviceImageName],
  ([newDevice, newSensorPoints, newImageName], [oldDevice, oldSensorPoints, oldImageName]) => {
    if (
      newDevice !== oldDevice ||
      // 这里的 JSON.stringify 比较对于大型或复杂对象可能性能不佳，但对于小数组通常可以接受
      JSON.stringify(newSensorPoints) !== JSON.stringify(oldSensorPoints) ||
      newImageName !== oldImageName
    ) {
      console.log(
        'LeftPanel: Device, sensorPoints, or imageName changed. Re-evaluating sensor box positions.',
      )
      // 核心修改点：
      // 如果图片文件名改变，重置 imageLoaded 状态，等待图片重新加载触发 onImageLoad
      if (newImageName !== oldImageName) {
        imageLoaded.value = false // 重置图片加载状态
        // 不需要在这里立即调用 positionSensorBoxes
        // 因为当图片加载完成后，onImageLoad 会自动调用它
      } else {
        // 如果只有设备或传感器数据变化，且图片未改变，则直接重新定位
        nextTick(() => {
          positionSensorBoxes()
        })
      }
    }
  },
  { deep: true },
) // deep: true 用于监听 sensorPoints 数组内部对象属性的改变 (如 latestValue)

// 监听 activeDeviceName 变化 (仅用于调试或按钮更新)
watch(
  () => props.activeDeviceName,
  (newVal) => {
    console.log('LeftPanel: Active device button updated:', newVal)
  },
)

// === 设备按钮相关的逻辑 ===
const emitSwitchDevice = (deviceName) => {
  emit('switch-device', deviceName)
}

const clearAndStartMonitor = async () => {
  console.log(
    'LeftPanel: Simulating Clear and Start Monitor action (calls backend /api/clear, /api/start_monitor).',
  )
  try {
    await fetch('/api/clear')
    await fetch('/api/start_monitor')
    alert('数据已清空并开始模拟！')
  } catch (error) {
    console.error('Failed to clear/start monitor:', error)
    alert('操作失败，请检查后端服务！')
  }
}

// ==========================================================
// 生命周期钩子
// ==========================================================
onMounted(() => {
  // 确保组件挂载时，如果图片已经完成加载（比如从缓存），也能正确执行定位
  if (deviceImageRef.value && deviceImageRef.value.complete) {
    imageLoaded.value = true
    nextTick(positionSensorBoxes)
  }

  let resizeTimer
  window.addEventListener('resize', () => {
    clearTimeout(resizeTimer)
    resizeTimer = setTimeout(() => {
      console.log('LeftPanel: Window resized. Re-calculating sensor box positions.')
      positionSensorBoxes()
    }, 200)
  })
})
</script>

<style scoped>
/* Left Panel 容器样式 */
.left-panel {
  flex: 3;
  padding: 20px;
  display: flex;
  flex-direction: column; /* 使子元素（图片区和按钮区）垂直排列 */
  justify-content: flex-start; /* 顶部对齐 */
  align-items: center; /* 子元素水平居中 */
  overflow: hidden;
  position: relative; /* 确保 sensor-box 可以相对于 .left-panel 绝对定位 */
  min-height: 0;
  box-sizing: border-box;
}

/* 图片和传感器方框的包裹区域 */
.image-section {
  width: 100%;
  height: 80%;
  display: flex; /* 使图片在内部居中 */
  justify-content: center;
  align-items: center;
  position: relative; /* 确保传感器方框可以相对于 image-section 定位 */
  overflow: hidden; /* 隐藏超出部分的图片 */
  min-height: 0;
}

.device-image {
  /* 这些属性确保图片等比例缩放并适应 image-section 容器 */
  max-width: 100%;
  max-height: 100%;
  object-fit: contain; /* 保持图片比例，适应容器，可能留白 */
  display: block;
  width: auto; /* 允许图片按比例缩放 */
  height: auto; /* 允许图片按比例缩放 */
  border-radius: 5px;
}

/* 传感器方框样式 */
.sensor-box {
  width: 60px;
  height: 20px;
  background-color: rgba(0, 0, 0, 0.6);
  border-radius: 4px;
  position: absolute; /* 绝对定位，其 top/left 将由 JS 计算并赋值 */
  transform: translate(-50%, -50%); /* 保持方框中心对准指定点 */
  cursor: pointer;
  z-index: 10;
  border: 2px solid; /* 边框颜色由 JS 动态设置 */
  color: white; /* 文本颜色由 JS 动态设置 */
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  font-size: 0.8em;
  text-align: center;
  line-height: 1.2;
  box-sizing: border-box;
  pointer-events: all;
  transition:
    background-color 0.3s,
    border-color 0.3s,
    color 0.3s;
}

.sensor-box:hover {
  background-color: rgba(0, 0, 0, 0.8);
}

.sensor-box .sensor-id {
  font-weight: bold;
  margin-bottom: 2px;
}

.sensor-box .sensor-value {
  font-size: 0.9em;
}

/* 底部设备控制按钮容器 */
.device-controls-inline {
  width: 100%;
  padding-top: 15px;
  border-top: 1px solid #eee;
  margin-top: 20px;
  flex-shrink: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
}

.device-controls-inline button {
  padding: 8px 15px;
  background-color: #4caf50;
  color: white;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  position: relative; /* 确保徽章可以相对于按钮定位 */
  transition:
    background-color 0.3s ease,
    border-color 0.3s;
}

.device-controls-inline button:hover {
  background-color: #45a049;
}

.device-controls-inline button.active {
  background-color: #3f51b5;
}

.device-controls-inline .control-button {
  background-color: #ff9800;
}

.device-controls-inline .control-button:hover {
  background-color: #fb8c00;
}

/* 新增：未处理报警的按钮样式 */
.device-controls-inline button.has-undisposed-alarms {
  border: 2px solid red;
  box-shadow: 0 0 8px rgba(255, 0, 0, 0.5);
  /* animation: pulse-red 1s infinite alternate; */
}

@keyframes pulse-red {
  /* from {
    box-shadow: 0 0 8px rgba(255, 0, 0, 0.5);
  }
  to {
    box-shadow: 0 0 15px rgba(255, 0, 0, 0.8);
  } */
}
/* 新增：未处理报警数量的红色标签样式 */
.alarm-badge {
  position: absolute;
  top: -10px; /* 向上偏移 */
  right: -10px; /* 向右偏移 */
  background-color: red;
  color: white;
  border-radius: 50%; /* 圆形 */
  padding: 6px 6px; /* 调整内边距 */
  font-size: 1em;
  font-weight: bold;
  min-width: 16px; /* 确保单数字也显示为圆形 */
  text-align: center;
  line-height: 1; /* 垂直居中 */
  box-shadow: 0 0 5px rgba(0, 0, 0, 0.3); /* 阴影 */
  animation: bounce-scale 0.5s infinite alternate; /* 跳动放大动画 */
}

@keyframes bounce-scale {
  0% {
    transform: scale(1);
  }
  100% {
    transform: scale(1);
  }
}
</style>
